package com.airsystem.pos.bengkel.controller;

import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import javax.accessibility.Accessible;
import javax.swing.JOptionPane;

import org.apache.log4j.Logger;

import com.airsystem.pos.bengkel.component.TableFrame;
import com.airsystem.pos.bengkel.entity.JenisTagihan;
import com.airsystem.pos.bengkel.entity.Tagihan;
import com.airsystem.pos.bengkel.entity.Tagihan.Type;
import com.airsystem.pos.bengkel.entity.loader.JenisTagihanLoader;
import com.airsystem.pos.bengkel.interfaces.ICallback;
import com.airsystem.pos.bengkel.interfaces.ILoader;
import com.airsystem.pos.bengkel.interfaces.IMaster;
import com.airsystem.pos.bengkel.interfaces.IServices;
import com.airsystem.pos.bengkel.interfaces.ISystem;
import com.airsystem.pos.bengkel.interfaces.ITable;
import com.airsystem.pos.bengkel.interfaces.IValidator;
import com.airsystem.pos.bengkel.model.MasterBillingDetailModel;
import com.airsystem.pos.bengkel.service.TagihanServices;
import com.airsystem.pos.bengkel.util.FormValidator;
import com.airsystem.pos.bengkel.view.dialog.MasterBillingDetailDialog;

/**
 * @author Fanny Irawan Sutawanir (fannyirawans@gmail.com)
 */
public class MasterBillingDetailController extends MasterBillingDetailModel implements IMaster, ITable, ISystem {
	private static final Logger LOG = Logger.getLogger(MasterBillingDetailController.class.getSimpleName());

	private final Map<String, Long> jenisTagihanMap;

	private final IServices<Tagihan> service;

	private final ILoader<Iterable<JenisTagihan>> jenistagihanLoader;

	private final IValidator<Accessible> formValidator;

	private final Tagihan tagihan;

	public MasterBillingDetailController() {
		super();

		service = new TagihanServices();
		jenistagihanLoader = new JenisTagihanLoader();

		formValidator = new FormValidator();

		jenisTagihanMap = new HashMap<String, Long>();

		tagihan = new Tagihan();
		tagihan.setChoice(Type.PERIODE.getFlag());
	}

	public void setup() {
		saveButton.setVisible(true);
		updateButton.setVisible(false);
		deleteButton.setVisible(false);

		saveButton.setEnabled(false);
		totalField.setEditable(false);
	}

	/**
	 * Database Action
	 */
	public void search() {
		dialogMasterBillingDetail = new MasterBillingDetailDialog();

		try {
			if (dialogMasterBillingDetail.getTagihanRow() == null) {
				cancel();
				return;
			}

			tagihanWrapper = dialogMasterBillingDetail.getTagihanRow();
			bulanCombo.setSelectedIndex(tagihanWrapper.getMonthIndex());
			tahunCombo.setSelectedIndex(tagihanWrapper.getYearIndex());

			TableFrame.deleteTable(tableTagihan, tableModel);
			for (Tagihan item : tagihanWrapper.getTagihans()) {
				Vector<String> vector = new Vector<String>();
				vector.add(item.getJenis_tagihan().getNama());
				vector.add(item.getBiaya().toString());

				tableModel.addRow(vector);
			}
			tableTagihan.setModel(tableModel);

			saveButton.setVisible(false);
			updateButton.setVisible(true);
			deleteButton.setVisible(true);

			doCount();
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
	}

	public void get() {
		throw new UnsupportedOperationException("Not implemented!");
	}

	public void reset() {
		jenisCombo.setSelectedIndex(0);
		biayaField.setText("");
		totalField.setText("");
		bulanCombo.setSelectedIndex(currentMonth);
		tahunCombo.setSelectedIndex(currentYear);
	}

	public void save() {
		if (!isFormValid(bulanCombo, tahunCombo)) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);

			return;
		}

		if (tableModel.getRowCount() == 0) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);

			return;
		}

		try {
			int rowCount = tableModel.getRowCount();
			for (int i = 0; i < rowCount; i++) {
				String jenis = tableModel.getValueAt(i, 0).toString();
				String biaya = tableModel.getValueAt(i, 1).toString();

				JenisTagihan jenisTagihan = new JenisTagihan();
				jenisTagihan.setId(jenisTagihanMap.get(jenis));

				Tagihan tagihan = new Tagihan();
				tagihan.setPeriode(getPeriode());

				tagihan.setBiaya(Long.parseLong(biaya));
				tagihan.setJenis_tagihan(jenisTagihan);

				service.saveOrUpdate(tagihan);
			}

			JOptionPane.showMessageDialog(this, "Simpan data sukses", "Pesan", JOptionPane.INFORMATION_MESSAGE);
			cancel();
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			JOptionPane.showMessageDialog(this, "Simpan data gagal!", "Pesan", JOptionPane.ERROR_MESSAGE);

			return;
		}
	}

	public void update() {
		if (!isFormValid(bulanCombo, tahunCombo)) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);

			return;
		}

		if (tableModel.getRowCount() == 0) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);

			return;
		}

		try {
			if (tableTagihan.isRowSelected(row)) {
				Iterable<Tagihan> tagihanLoop = service.select(tagihan);
				for (Tagihan item : tagihanLoop) {
					service.delete(item);
				}
				edit();

				int rowCount = tableModel.getRowCount();
				for (int i = 0; i < rowCount; i++) {
					String jenis = tableModel.getValueAt(i, 0).toString();
					String biaya = tableModel.getValueAt(i, 1).toString();

					JenisTagihan jenisTagihan = new JenisTagihan();
					jenisTagihan.setId(jenisTagihanMap.get(jenis));

					Tagihan tagihan = new Tagihan();
					tagihan.setPeriode(getPeriode());

					tagihan.setBiaya(Long.parseLong(biaya));
					tagihan.setJenis_tagihan(jenisTagihan);

					service.saveOrUpdate(tagihan);
				}
			} else {
				JOptionPane.showMessageDialog(this, "Silahkan pilih data!", "Pesan", JOptionPane.WARNING_MESSAGE);
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			JOptionPane.showMessageDialog(this, "Ubah data gagal!", "Pesan", JOptionPane.ERROR_MESSAGE);

			return;
		}
	}

	public void delete() {
		if (!isFormValid(bulanCombo, tahunCombo)) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);

			return;
		}

		if (tableModel.getRowCount() == 0) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);

			return;
		}

		try {
			if (tableTagihan.isRowSelected(row)) {
				String jenis = tableModel.getValueAt(row, 0).toString();
				String biaya = tableModel.getValueAt(row, 1).toString();

				JenisTagihan jenisTagihan = new JenisTagihan();
				jenisTagihan.setId(jenisTagihanMap.get(jenis));

				Tagihan tagihan = new Tagihan();
				tagihan.setPeriode(getPeriode());
				tagihan.setBiaya(Long.parseLong(biaya));
				tagihan.setJenis_tagihan(jenisTagihan);

				service.delete(tagihan);
				remove();
			} else {
				JOptionPane.showMessageDialog(this, "Silahkan pilih data!", "Pesan", JOptionPane.WARNING_MESSAGE);
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			JOptionPane.showMessageDialog(this, "Hapus data gagal!", "Pesan", JOptionPane.ERROR_MESSAGE);

			return;
		}
	}

	public void cancel() {
		TableFrame.deleteTable(tableTagihan, tableModel);
		reset();
		setup();
	}

	/**
	 * Table Action
	 */
	public void init() {
		jenisCombo.setSelectedItem(tableTagihan.getValueAt(row, 0).toString());
		biayaField.setText(tableTagihan.getValueAt(row, 1).toString());

		if (saveButton.isVisible()) {
			updateButton.setVisible(true);
			deleteButton.setVisible(true);
		}

		doCount();
	}

	public void add() {
		if (!isFormValid(jenisCombo, biayaField)) {
			return;
		}

		String jenisTagihan = jenisCombo.getSelectedItem().toString();
		boolean isExist = false;
		for (int i = 0; i < tableTagihan.getRowCount(); i++) {
			if (jenisTagihan.equalsIgnoreCase(tableTagihan.getValueAt(i, 0).toString())) {
				isExist = true;
			}
		}

		if (isExist) {
			JOptionPane.showMessageDialog(this, "Data sudah ada!", "Pesan", JOptionPane.WARNING_MESSAGE);

			return;
		}

		Vector<String> vector = new Vector<String>();
		vector.add(jenisTagihan);
		vector.add(biayaField.getText().trim());

		tableModel.addRow(vector);
		tableTagihan.setModel(tableModel);

		if (saveButton.isVisible()) {
			saveButton.setEnabled(true);
			reset();
		}

		doCount();
	}

	public void edit() {
		if (!isFormValid(jenisCombo, biayaField)) {
			return;
		}
		int rowCount = tableModel.getRowCount();

		String jenisTagihan = jenisCombo.getSelectedItem().toString();
		for (int i = 0; i < rowCount; i++) {
			if (jenisTagihan.equalsIgnoreCase(tableTagihan.getValueAt(i, 0).toString())) {
				String biaya = biayaField.getText().trim();
				tableTagihan.setValueAt(biaya, i, 1);

				reset();
				doCount();
				return;
			}
		}

		JOptionPane.showMessageDialog(this, "Data tidak ditemukan!", "Pesan", JOptionPane.WARNING_MESSAGE);
		reset();
	}

	public void remove() {
		tableModel.removeRow(row);
		reset();

		if (saveButton.isVisible()) {
			updateButton.setVisible(false);
			deleteButton.setVisible(false);
		}

		if (tableTagihan.getRowCount() == 0 && !saveButton.isVisible()) {
			JOptionPane.showMessageDialog(this, "Hapus data sukses", "Pesan", JOptionPane.INFORMATION_MESSAGE);
			cancel();
		}

		doCount();
	}

	public void load() {
		jenistagihanLoader.load(new ICallback<Iterable<JenisTagihan>>() {
					public void get(Iterable<JenisTagihan> result) {
						jenisCombo.addItem("-- PILIH --");
						for (JenisTagihan item : result) {
							jenisTagihanMap.put(item.getNama(), item.getId());
							jenisCombo.addItem(item.getNama());
						}
					}
				});
	}

	private boolean isFormValid(Accessible... component) {
		try {
			return formValidator.isValid(component);
		} catch (IllegalArgumentException e) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);
		} catch (IllegalStateException e) {
			JOptionPane.showMessageDialog(this, "Data kosong!", "Pesan", JOptionPane.WARNING_MESSAGE);
		}

		return false;
	}

	private void doCount() {
		int index = tableTagihan.getRowCount();
		long total = 0;

		for (int i = 0; i < index; i++) {
			total += Long.parseLong(tableTagihan.getValueAt(i, 1).toString());
		}

		totalField.setText(String.valueOf(total));
	}
}